package com.alibaba.citrus.cr.mn.order.center.facade.function.check;

import com.alibaba.citrus.cr.common.enums.ordercenter.*;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.AssertUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.JsonUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.BaseDataServiceAdapter;
import com.epoch.app.mnordercenter.model.dto.DictionaryResponse;
import com.epoch.app.mnordercenter.model.dto.SalesOrderAtomCreateLineRequest;
import com.epoch.app.mnordercenter.model.dto.SalesOrderAtomCreateRequest;
import com.epoch.app.mnordercenter.model.dto.SalesOrderBizCreateRequest;
import com.epoch.app.mnordercenter.orderbaserequest.OrderAtomCreateResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhangxiaorui
 * @ClassName SalesOrderBizCreateParamsCheck
 * @description: 销售订单商业创建入参校验
 * @date 2023/05/11 16:35
 * @version: 1.0
 */
@Service("salesOrderDirectBizCreateParamsCheck")
public class SalesOrderDirectBizCreateParamsCheck extends AbstractOrderParamsCheckService<SalesOrderBizCreateRequest, OrderAtomCreateResponse> {

    @Resource
    private BaseDataServiceAdapter baseDataServiceAdapter;

    @Override
    public void paramsNotBlankCheck(List<SalesOrderBizCreateRequest> requestList, List<OrderAtomCreateResponse> responseList) {
        AssertUtils.isTrue(CollectionUtils.isEmpty(requestList), "OC-01-001-01-15-001", "单据列表");
        AssertUtils.isTrue(requestList.size() > 100, "OC-01-001-01-15-004", "单据列表", requestList.size(), "100");
        requestList.forEach(t -> {
            AssertUtils.isTrue(StringUtils.isBlank(t.getFromSys()), "OC-01-001-01-15-001", "来源系统编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getBusinessType()), "OC-01-001-01-15-001", "业态编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getBusinessUnitCode()), "OC-01-001-01-15-001", "业务单元编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getOrderChannelCode()), "OC-01-001-01-15-001", "订单渠道编码");

            AssertUtils.isTrue(StringUtils.isBlank(t.getSourceOrderNo()), "OC-01-001-01-15-001", "来源单号");
            AssertUtils.isTrue(StringUtils.isBlank(t.getProductGroupCode()), "OC-01-001-01-15-001", "产品组编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getBusinessChannel()), "OC-01-001-01-15-001", "业务渠道编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getSalesOrganizationCode()), "OC-01-001-01-15-001", "销售组织编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getCustomerCode()), "OC-01-001-01-15-001", "客户售达方编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getShipToPartyCode()), "OC-01-001-01-15-001", "客户送达方编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getGroupCustomerCode()), "OC-01-001-01-15-001", "集团售达方编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getGroupShipToPartyCode()), "OC-01-001-01-15-001", "集团送达方编码");


            AssertUtils.isTrue(StringUtils.isBlank(t.getSalesOrderType()), "OC-01-001-01-15-001", "订单类型编码");

            AssertUtils.isTrue(StringUtils.isBlank(t.getDeliveryMethodCode()), "OC-01-001-01-15-001", "配送方式编码");
            AssertUtils.isTrue(StringUtils.isBlank(t.getExpectedDeliveryDate()), "OC-01-001-01-15-001", "期望交货日期");

            AssertUtils.isTrue(StringUtils.isBlank(t.getCreatorCode()), "OC-01-001-01-15-001", "创建人工号");

            AssertUtils.isTrue(CollectionUtils.isEmpty(t.getOrderDetails()), "OC-01-001-01-15-001", "单据明细");
            AssertUtils.isTrue(t.getOrderDetails().size() > 100, "OC-01-001-01-15-004", "单据明细", t.getOrderDetails().size(), "100");


            // 校验单据明细
            t.getOrderDetails().forEach(detail -> {
                AssertUtils.isTrue(StringUtils.isBlank(detail.getSourceLineNum()), "OC-01-001-01-15-001", "来源单行号");
                 AssertUtils.isTrue(StringUtils.isBlank(detail.getProductCode()), "OC-01-001-01-15-001", "物料编码");
                AssertUtils.isTrue(StringUtils.isBlank(detail.getProductQuantity()), "OC-01-001-01-15-001", "销售数量");
                AssertUtils.isTrue(StringUtils.isBlank(detail.getSalesUnitCode()), "OC-01-001-01-15-001", "销售单位编码");
                AssertUtils.isTrue(StringUtils.isBlank(detail.getProductionDate()), "OC-01-001-01-15-001", "生产日期");

                //二选一必填 【发货仓编码】与【工厂+库存地点】二选一必填
                if (StringUtils.isBlank(detail.getShippingWarehouseCode())) {
                    if (StringUtils.isBlank(detail.getDeliveryFactoryCode()) && StringUtils.isBlank(detail.getStockCode())) {
                        throw new FunctionException("OC-01-001-01-15-010", "逻辑仓库编码、交货工厂编码、库存地点编码");
                    }
                    AssertUtils.isTrue(StringUtils.isBlank(detail.getDeliveryFactoryCode()), "OC-01-001-01-15-001", "交货工厂编码");
                    AssertUtils.isTrue(StringUtils.isBlank(detail.getStockCode()), "OC-01-001-01-15-001", "库存地点编码");
                }
            });

            // 校验单据明细行号是否重复
            List<String> sameSourceLines = t.getOrderDetails().stream()
                    .map(SalesOrderAtomCreateLineRequest::getSourceLineNum)
                    .collect(Collectors.toMap(p -> p, p -> 1, Integer::sum))
                    .entrySet().stream().filter(entry -> entry.getValue() > 1)
                    .map(Map.Entry::getKey).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(sameSourceLines)) {
                throw new FunctionException("OC-01-001-01-15-002", "来源单行号", StringUtils.join(sameSourceLines, ","));
            }
        });

        // 校验来源单号是否重复
        List<String> sameSourceOrderNos = requestList.stream()
                .map(SalesOrderAtomCreateRequest::getSourceOrderNo)
                .collect(Collectors.toMap(t -> t, t -> 1, Integer::sum))
                .entrySet().stream().filter(entry -> entry.getValue() > 1)
                .map(Map.Entry::getKey).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(sameSourceOrderNos)) {
            throw new FunctionException("OC-01-001-01-15-002", "来源单号", StringUtils.join(sameSourceOrderNos, ","));
        }
    }

    @Override
    public void paramsLengthCheck(List<SalesOrderBizCreateRequest> requestList, List<OrderAtomCreateResponse> responseList) {
        requestList.forEach(t -> {
            AssertUtils.isNumber(t.getBusinessType(), true, "OC-01-001-01-15-006", "业态编码");
            AssertUtils.lengthCheck(t.getFromSys(), 50, true, "OC-01-001-01-15-004", "来源系统编码");
            AssertUtils.lengthCheck(t.getBusinessType(), 10, true, "OC-01-001-01-15-004", "业态编码");
            AssertUtils.lengthCheck(t.getBusinessUnitCode(), 50, true, "OC-01-001-01-15-004", "业务单元编码");
            AssertUtils.lengthCheck(t.getOrderChannelCode(), 50, true, "OC-01-001-01-15-004", "订单渠道编码");
            AssertUtils.lengthCheck(t.getSourceOrderNo(), 50, true, "OC-01-001-01-15-004", "来源单号");
            AssertUtils.lengthCheck(t.getProductGroupCode(), 50, true, "OC-01-001-01-15-004", "产品组编码");
            AssertUtils.lengthCheck(t.getPreOrderNo(), 50, false, "OC-01-001-01-15-004", "预报订单号");


            AssertUtils.lengthCheck(t.getBusinessChannel(), 50, true, "OC-01-001-01-15-004", "业务渠道编码");
            AssertUtils.lengthCheck(t.getSalesOrganizationCode(), 50, true, "OC-01-001-01-15-004", "销售组织编码");
            AssertUtils.lengthCheck(t.getCustomerCode(), 50, true, "OC-01-001-01-15-004", "客户售达方编码");
            AssertUtils.lengthCheck(t.getShipToPartyCode(), 50, true, "OC-01-001-01-15-004", "客户送达方编码");
            AssertUtils.lengthCheck(t.getGroupCustomerCode(), 50, true, "OC-01-001-01-15-004", "集团售达方编码");
            AssertUtils.lengthCheck(t.getGroupShipToPartyCode(), 50, true, "OC-01-001-01-15-004", "集团送达方编码");

            AssertUtils.lengthCheck(t.getSalesOrderType(), 10, true, "OC-01-001-01-15-004", "订单类型编码");
            AssertUtils.lengthCheck(t.getDeliveryMethodCode(), 50, true, "OC-01-001-01-15-004", "配送方式编码");
            AssertUtils.lengthCheck(t.getKaSystem(), 50, false, "OC-01-001-01-15-004", "KA系统");
            AssertUtils.lengthCheck(t.getKaArea(), 50, false, "OC-01-001-01-15-004", "KA大区");
            AssertUtils.lengthCheck(t.getFulfillmentPriority(), 10, false, "OC-01-001-01-15-004", "履约优先级");
            AssertUtils.lengthCheck(t.getCustomerPurchaseOrderNo(), 50, false, "OC-01-001-01-15-004", "客户采购订单号");
            AssertUtils.lengthCheck(t.getCustomerPurchaseDate(), 10, false, "OC-01-001-01-15-004", "客户采购订单日期");
            if (StringUtils.isNotBlank(t.getCustomerPurchaseDate())) {
                AssertUtils.isTrue(!DateUtils.isDateFormat(t.getCustomerPurchaseDate()), "OC-00-001-01-15-001", "客户采购订单日期");
            }
            AssertUtils.lengthCheck(t.getSalesChannelCode(), 50, false, "OC-01-001-01-15-004", "销售渠道编码");
            AssertUtils.lengthCheck(t.getSalesChannelName(), 50, false, "OC-01-001-01-15-004", "销售渠道名称");
            AssertUtils.lengthCheck(t.getSalesDepartmentCode(), 50, false, "OC-01-001-01-15-004", "销售部门编码");
            AssertUtils.lengthCheck(t.getSalesDepartmentName(), 50, false, "OC-01-001-01-15-004", "销售部门名称");
            AssertUtils.lengthCheck(t.getExpectedDeliveryDate(), 10, true, "OC-01-001-01-15-004", "期望交货日期");
            AssertUtils.isTrue(!DateUtils.isDateFormat(t.getExpectedDeliveryDate()), "OC-00-001-01-15-001", "期望交货日期");

            AssertUtils.lengthCheck(t.getCreatorCode(), 50, true, "OC-01-001-01-15-004", "创建人工号");

            AssertUtils.isDateOrTime(t.getSourceOrderTime(), 19, false, DateUtils.DATETIME_FORMAT, "来单时间");

            AssertUtils.lengthCheck(t.getOrderReasonCode(), 50, false, "OC-01-001-01-15-004", "订单原因编码");
            AssertUtils.lengthCheck(t.getNote(), 255, false, "OC-01-001-01-15-004", "订单头备注");
            AssertUtils.lengthCheck(t.getBizFeatures(), 1024, false, "OC-01-001-01-15-004", "扩展字段（主单）");
            // 校验扩展字段是否为JSON格式
            AssertUtils.isTrue(!JsonUtils.isValidJson(t.getBizFeatures()), "OC-00-001-01-15-001", "扩展字段（主单）");

            if (CollectionUtils.isNotEmpty(t.getOrderBizTag())) {
                AssertUtils.isTrue(t.getOrderBizTag().size() > 10, "OC-01-001-01-15-004", "订单标签集合", t.getOrderBizTag().size(), "10");
                for (String orderTag : t.getOrderBizTag()) {
                    AssertUtils.lengthCheck(orderTag, 50, "OC-01-001-01-15-004", "订单标签");
                }
            }
            t.getOrderDetails().forEach(detail -> {
                AssertUtils.lengthCheck(detail.getSourceLineNum(), 10, true, "OC-01-001-01-15-004", "来源单行号");
                AssertUtils.lengthCheck(detail.getProductCode(), 50, true, "OC-01-001-01-15-004", "物料编码");
                AssertUtils.isWholeNumber(detail.getProductQuantity(), true, "OC-01-001-01-15-009", "销售数量", "销售数量须为正整数");
                AssertUtils.lengthCheck(detail.getProductQuantity(), 10, true, "OC-01-001-01-15-004", "销售数量");
                AssertUtils.isTrue(BigDecimal.ZERO.compareTo(new BigDecimal(detail.getProductQuantity())) >= 0, "OC-01-001-01-15-009", "销售数量", "销售数量须为正整数");
                AssertUtils.isTrue(new BigDecimal("2147483647").compareTo(new BigDecimal(detail.getProductQuantity())) < 0, "OC-01-001-01-15-009", "销售数量", "最大2147483647");
                AssertUtils.lengthCheck(detail.getSalesUnitCode(), 50, true, "OC-01-001-01-15-004", "销售单位编码");
                AssertUtils.lengthCheck(detail.getDeliveryFactoryCode(), 50, false, "OC-01-001-01-15-004", "交货工厂编码");
                AssertUtils.lengthCheck(detail.getStockCode(), 50, false, "OC-01-001-01-15-004", "库存地点编码");
                AssertUtils.lengthCheck(detail.getShippingWarehouseCode(), 50, false, "OC-01-001-01-15-004", "逻辑仓库编码");
                AssertUtils.lengthCheck(detail.getNote(), 255, false, "OC-01-001-01-15-004", "订单行备注");
                AssertUtils.lengthCheck(detail.getBizFeatures(), 1024, false, "OC-01-001-01-15-004", "扩展字段（子单）");

                // 校验扩展字段是否为JSON格式
                AssertUtils.isTrue(!JsonUtils.isValidJson(detail.getBizFeatures()), "OC-00-001-01-15-001", "扩展字段（子单）");
                AssertUtils.lengthCheck(detail.getConfirmQuantity(), 10, false, "OC-01-001-01-15-004", "确认数量");
                if(StringUtils.isNotBlank(detail.getConfirmQuantity())){
                    AssertUtils.isWholeNumber(detail.getConfirmQuantity(), true, "OC-01-001-01-15-009", "确认数量", "确认数量须为正整数");
                    AssertUtils.isTrue(BigDecimal.ZERO.compareTo(new BigDecimal(detail.getConfirmQuantity())) >= 0, "OC-01-001-01-15-009", "确认数量","确认数量须为正整数");
                    AssertUtils.isTrue(new BigDecimal("2147483647").compareTo(new BigDecimal(detail.getConfirmQuantity())) < 0, "OC-01-001-01-15-009", "确认数量", "最大2147483647");

                }
                AssertUtils.lengthCheck(detail.getSourceQuantity(), 10, false, "OC-01-001-01-15-004", "来单数量");
                if(StringUtils.isNotBlank(detail.getSourceQuantity())) {
                    AssertUtils.isWholeNumber(detail.getSourceQuantity(), true, "OC-01-001-01-15-009", "来单数量", "来单数量须为正整数");
                    AssertUtils.isTrue(BigDecimal.ZERO.compareTo(new BigDecimal(detail.getSourceQuantity())) >= 0, "OC-01-001-01-15-009", "来单数量","来单数量须为正整数");
                    AssertUtils.isTrue(new BigDecimal("2147483647").compareTo(new BigDecimal(detail.getSourceQuantity())) < 0, "OC-01-001-01-15-009", "来单数量", "最大2147483647");

                }
                AssertUtils.lengthCheck(StringUtils.isBlank(detail.getSourcePrice()) ? null : detail.getSourcePrice().split("\\.")[0], 10, false, "OC-01-001-01-15-004", "来单价格");

                if(StringUtils.isNotBlank(detail.getSourcePrice())) {
                    AssertUtils.isNumber(detail.getSourcePrice(), false, "OC-01-001-01-15-006", "来单价格");
                    AssertUtils.isTrue(BigDecimal.ZERO.compareTo(new BigDecimal(detail.getSourcePrice())) > 0, "OC-01-001-01-15-009", "来单价格","来单价格须为正整数");
                    AssertUtils.isTrue(new BigDecimal("2147483647").compareTo(new BigDecimal(detail.getSourcePrice())) < 0, "OC-01-001-01-15-009", "来单价格", "最大2147483647");
                }



                AssertUtils.lengthCheck(detail.getSourceUnit(), 50, false, "OC-01-001-01-15-004", "来单单位");

                // 生产日期
                AssertUtils.lengthCheck(detail.getProductionDate(), 10, true, "OC-01-001-01-15-004", "生产日期");
                if (StringUtils.isNotBlank(detail.getProductionDate())) {
                    AssertUtils.isTrue(!DateUtils.isDateFormat(detail.getProductionDate()), "OC-00-001-01-15-001", "生产日期");
                }
            });
        });
    }

    @Override
    public void paramsEnumDictCheck(List<SalesOrderBizCreateRequest> requestList, List<OrderAtomCreateResponse> responseList) {
        // 系统来源
        List<DictionaryResponse> fromSysResponseList = baseDataServiceAdapter.queryDictionarys(DictionaryTypeEnum.FROM_SYS.getCode());
        Map<String, DictionaryResponse> fromSysMap = fromSysResponseList.stream().collect(Collectors.toMap(DictionaryResponse::getCode, Function.identity(), (k1, k2) -> k2));
        // 业态
        List<DictionaryResponse> businessTypeResponseList = baseDataServiceAdapter.queryDictionarys(DictionaryTypeEnum.BUSINESS_TYPE.getCode());
        Map<String, DictionaryResponse> businessTypeMap = businessTypeResponseList.stream().collect(Collectors.toMap(DictionaryResponse::getCode, Function.identity(), (k1, k2) -> k2));
        // 业务单元编码
        Map<String, DictionaryResponse> businessUnitMap = new HashMap<>();
        List<DictionaryResponse> businessUnitList = baseDataServiceAdapter.queryDictionarys(DictionaryTypeEnum.BUSINESS_UNIT_CODE.getCode());
        if (CollectionUtils.isNotEmpty(businessUnitList)) {
            businessUnitMap = businessUnitList.stream().collect(Collectors.toMap(DictionaryResponse::getCode, Function.identity(), (x1, x2) -> x2));
        }

        Map<String, DictionaryResponse> finalBusinessUnitMap = businessUnitMap;
        requestList.forEach(t -> {
            if (fromSysMap.get(t.getFromSys()) == null) {
                throw new FunctionException("OC-01-001-01-15-006", "来源系统编码");
            }
            DictionaryResponse dictionaryResponse = businessTypeMap.get(t.getBusinessType());
            if (dictionaryResponse == null) {
                throw new FunctionException("OC-01-001-01-15-006", "业态编码");
            }
            DictionaryResponse businessUnit = finalBusinessUnitMap.get(t.getBusinessUnitCode());
            if (Objects.isNull(businessUnit)) {
                throw new FunctionException("OC-01-001-01-15-006", "业务单元编码");
            }
            t.setBusinessUnitName(businessUnit.getName());
            //设置业态名称
            t.setBusinessTypeName(dictionaryResponse.getName());

            // 校验订单渠道编码
            if (StringUtils.isNotBlank(t.getOrderChannelCode())) {
                OrderChannelEnum orderChannelEnum = OrderChannelEnum.of(t.getOrderChannelCode());
                Optional.ofNullable(orderChannelEnum).orElseThrow(() -> new FunctionException("OC-01-001-01-15-006", "订单渠道编码"));
                t.setOrderChannelName(orderChannelEnum.getDesc());
            }

            //销售订单类型编码
            SalesOrderTypeEnum salesOrderTypeEnum = SalesOrderTypeEnum.of(t.getSalesOrderType());
            if (Objects.isNull(salesOrderTypeEnum)) {
                throw new FunctionException("OC-01-001-01-15-006", "订单类型编码");
            }
            t.setSalesOrderTypeName(salesOrderTypeEnum.getDesc());
            // 校验配送方式编码
            SalesOrderDeliveryMethodEnum salesOrderDeliveryMethodEnum = SalesOrderDeliveryMethodEnum.of(t.getDeliveryMethodCode());
            Optional.ofNullable(salesOrderDeliveryMethodEnum).orElseThrow(() -> new FunctionException("OC-01-001-01-15-006", "配送方式编码"));
            t.setDeliveryMethodName(salesOrderDeliveryMethodEnum.getDesc());
            // 校验订单原因编码
            if (StringUtils.isNotBlank(t.getOrderReasonCode())) {
                SalesOrderReasonEnum salesOrderReasonEnum = SalesOrderReasonEnum.of(t.getOrderReasonCode());
                Optional.ofNullable(salesOrderReasonEnum).orElseThrow(() -> new FunctionException("OC-01-001-01-15-006", "订单原因编码"));
            }
            // 订单标签校验
            if (CollectionUtils.isNotEmpty(t.getOrderBizTag())) {
                for (String orderTag : t.getOrderBizTag()) {
                    AssertUtils.isTrue(!OrderBizTagEnum.codes().contains(orderTag), "OC-01-001-01-15-006", "订单标签");
                }
                //是否重复
                int size = t.getOrderBizTag().size();
                List<String> distinct = t.getOrderBizTag().stream().distinct().collect(Collectors.toList());
                AssertUtils.isTrue(distinct.size() != size ,"OC-01-001-01-15-009", "订单标签","订单标签重复");

            }
            //履约方式
            t.setFulfillmentTypeCode(FulfillmentTypeEnum.CENTRAL_DELIVERY.getCode());
            //履约优先级
            if (StringUtils.isNotBlank(t.getFulfillmentPriority())) {
                AssertUtils.isTrue(Objects.isNull(FulfillmentPriorityEnum.of(t.getFulfillmentPriority())), "OC-01-001-01-15-006", "履约优先级");
            }else{
                //不传的情况下默认“普通”
                t.setFulfillmentPriority(FulfillmentPriorityEnum.NORMAL.getCode());
            }
            if(StringUtils.isBlank(t.getAutoFulfillment())){
                //设置默认值不传的情况下默认“是”
                t.setAutoFulfillment(AutoFulfillmentEnum.TRUE.getCode());
            }else {
                if(!isBoolean(t.getAutoFulfillment())){
                    throw new FunctionException("OC-01-001-01-15-009", "是否自动履约","是否自动履约只支持true/false");
                }
            }
            //销售单位
            for (SalesOrderAtomCreateLineRequest p : t.getOrderDetails()) {
                StockUnitEnum salesUnit = StockUnitEnum.of(p.getSalesUnitCode());
                Optional.ofNullable(salesUnit).orElseThrow(() -> new FunctionException("OC-01-001-01-15-006", "销售单位编码"));
                p.setSalesUnitName(salesUnit.getDesc());
            }
        });
    }
    private boolean isBoolean(String param){
        return  "true".equals(param) || "false".equals(param);
    }
}
